﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.IO;
using HU8.Helpers.Files.Resource;
using System.Web.Script.Services;
using HU8.Helpers.Base;
using HU8.Helpers.Files;
using HU8.Web.FileExplorer.FileExplorer.Config;

namespace HU8.Web.FileExplorer.FileExplorer.WebServices
{
    /// <summary>
    /// FileService 的摘要说明
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务，请取消对下行的注释。
    [System.Web.Script.Services.ScriptService]
    public class FileService : System.Web.Services.WebService
    {
        private FileExplorerConfig config;
        private LanguageDictionary dictionary;

        public FileService()
        {
            config = new FileExplorerConfig(Server);
            dictionary = new LanguageDictionary(config.Language, Server);//会有点问题
        }

        public string GetBasePath()
        {
            return Server.MapPath(config.BasePath);
        }

        public string GetTempPath()
        {
            string p = config.TempPath;
            string serverPath = Server.MapPath(p);
            if(!Directory.Exists(serverPath)){
                Directory.CreateDirectory(serverPath);
            }
            return p ;
        }

        public string GetThumbPath()
        {
            string p = config.ThumbConfig.ThumbPath;
            string serverPath = Server.MapPath(p);
            if (!Directory.Exists(serverPath))
            {
                Directory.CreateDirectory(serverPath);
            }
            return p;
        }

        /// <summary>
        /// 文件信息
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public FolderFile GetFileInfo(string path)
        {
            path = path.Replace("~", config.BasePath);
            string physicalPath = Server.MapPath(path);
            FolderFile fi = new FolderFile(physicalPath, GetBasePath());
            return fi;
        }
        /// <summary>
        /// 文件夹信息
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Folder GetFolderInfo(string path)
        {
            path = path.Replace("~", config.BasePath);
            string physicalPath = Server.MapPath(path);
            Folder di = new Folder(physicalPath, GetBasePath(), config.Language);
            //di.Folders = FileHelper.GetFolderList(physicalPath, GetBasePath());
            //di.Files = FileHelper.GetFileList(physicalPath, GetBasePath());
            return di;
        }
        /// <summary>
        /// 文件夹信息
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Folder GetFolder(string path)
        {
            path = path.Replace("~/", config.BasePath);
            string physicalPath = Server.MapPath(path);
            Folder di = new Folder(physicalPath, GetBasePath(), config.Language);

            try
            {
                List<Folder> folders = FileHelper.GetFolderList(physicalPath, GetBasePath());
                di.Folders = new List<Folder>();
                foreach (Folder f in folders)
                {
                    if (Allowed(f.RelativePath, "r"))
                    {
                        di.Folders.Add(f);
                    }
                }

                List<FolderFile> files = FileHelper.GetFileList(physicalPath, GetBasePath());
                di.Files = new List<FolderFile>();
                foreach (FolderFile f in files)
                {
                    if (Allowed(f.RelativePath, "r"))
                    {
                        di.Files.Add(f);
                    }
                }
            }
            catch (Exception ex)
            {
                di.ErrorOccured = true;
                di.Error += ex.Message;
            }
            try
            {
                //制造一些缩略图
                ThumbnailHelper.GenerateThumbnailsInFolder(physicalPath, GetBasePath(), Server.MapPath(GetThumbPath()));
            }
            catch (Exception ex)
            {
                //缩略图错误不算错误。。。
                //di.ErrorOccured = true;
                di.Error += ex.Message;
            }
            return di;
        }

        /// <summary>
        /// 是否允许用户执行操作
        /// </summary>
        /// <param name="relativePath"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public bool Allowed(string relativePath, string type)
        {
            relativePath = relativePath.Trim();
            IEnumerable<ProtectedPath> protectedPaths;
            if(type == "r"){
                protectedPaths = config.ProtectedPaths.Where(p => p.RelativePath == relativePath && !p.AllowRead);
            }
            else if (type == "w")
            {
                protectedPaths = config.ProtectedPaths.Where(p => p.RelativePath == relativePath && !p.AllowWrite);
            }
            else // delete
            {
                protectedPaths = config.ProtectedPaths.Where(p => p.RelativePath == relativePath && !p.AllowDelete);
            }

            if (protectedPaths.Count() > 0)
            {
                foreach (ProtectedPath p in protectedPaths)
                {
                    foreach (string role in p.OverrideRoles)
                    {
                        if (User.IsInRole(role) || role == "Everyone")
                        {
                            return true;
                        }
                    }
                }
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// 获取文件夹
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public List<Folder> GetFolders(string path)
        {
            path = path.Replace("~", config.BasePath);
            string physicalPath = Server.MapPath(path);
            return FileHelper.GetFolderList(physicalPath, GetBasePath());
        }

        /// <summary>
        /// 获取文件集
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public List<FolderFile> GetFiles(string path)
        {
            path = path.Replace("~", config.BasePath);
            string physicalPath = Server.MapPath(path);
            return FileHelper.GetFileList(physicalPath, GetBasePath());
        }


        #region Operation
        /// <summary>
        /// 删除文件，或者文件夹
        /// </summary>
        /// <param name="paths"></param>
        /// <param name="recursive"></param>
        /// <returns></returns>
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public JsonResponse Delete(string paths, bool recursive = false)
        {
            string filteredPaths = "";
            foreach (string p in paths.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
            {
                ///string fp = p.Replace("~/", config.BasePath);
                if (Allowed(p, "x"))
                {
                    filteredPaths += p + ",";
                }
            }
            if (string.IsNullOrEmpty(filteredPaths))
            {
                JsonResponse response = new JsonResponse();
                response.success = false;
                response.message = "所选的文件和文件夹被保护，您无法删除这些文件或文件夹";
                return response;
            }
            else
            {
                filteredPaths = filteredPaths.Replace("~/", GetBasePath());
                return FileHelper.DeleteFiles(filteredPaths, recursive);
            }
        }
        
        /// <summary>
        /// 重命名文件，或者文件夹
        /// </summary>
        /// <param name="path"></param>
        /// <param name="newName"></param>
        /// <returns></returns>
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public JsonResponse Rename(string path, string newName)
        {
            path = path.Replace("~", config.BasePath);
            if (Allowed(path, "w"))
            {
                path = Server.MapPath(path);
                return FileHelper.Rename(path, newName);
            }
            else
            {
                JsonResponse response = new JsonResponse();
                response.success = false;
                response.message = "所选的文件和文件夹被保护，您无法修改这些文件或文件夹";
                return response;
            }
        }

        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public JsonResponse Cut(string paths, string newPath)
        {
            paths = paths.Replace("~/", GetBasePath());
            newPath = newPath.Replace("~", config.BasePath);
            newPath = Server.MapPath(newPath);
            return FileHelper.Cut(paths, newPath);
        }

        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public JsonResponse Copy(string paths, string newPath)
        {
            paths = paths.Replace("~/", GetBasePath());
            newPath = newPath.Replace("~", config.BasePath);
            newPath = Server.MapPath(newPath);
            return FileHelper.Copy(paths, newPath);
        }

        #endregion

        #region Zip Operation
        /// <summary>
        /// 将选中的文件，文件夹压缩到ZIP文件里
        /// </summary>
        /// <param name="paths"></param>
        /// <param name="dest"></param>
        /// <param name="zipName"></param>
        /// <param name="includeRoot"></param>
        /// <returns></returns>
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public JsonResponse Compress(string paths, string dest, string zipName)
        {
            paths = paths.Replace("~/", GetBasePath());
            dest = dest.Replace("~/", config.BasePath);

            string saveTo = Server.MapPath(Path.Combine(dest, zipName));
            return ZipHelper.GenerateZipFile(paths, saveTo, "", true);
        }
        /// <summary>
        /// 解压缩ZIP文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="dest"></param>
        /// <param name="overwrite"></param>
        /// <returns></returns>
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public JsonResponse Extract(string path, string dest, bool overwrite = true)
        {
            path = path.Replace("~/", config.BasePath);
            dest = dest.Replace("~/", config.BasePath);

            string zipPath = Server.MapPath(path);
            string extractTo = Server.MapPath(dest);
            return ZipHelper.UnzipFile(zipPath, extractTo, overwrite);
        }
        #endregion

        /// <summary>
        /// 下载选中文件
        /// 1.压缩选中文件
        /// 2.返回压缩好的文件下载地址
        /// </summary>
        /// <param name="paths"></param>
        /// <returns></returns>
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public JsonResponse DownloadFiles(string paths)
        {
            if (!paths.Contains(",") && paths.Contains("."))
            {
                //如果只是一个文件的话，直接下载咯
                JsonResponse downloadRes = new JsonResponse();
                downloadRes.message = paths.Replace("~/", config.BasePath).Replace("~", "");
                downloadRes.success = true;
                return downloadRes;
            }
            else
            {
                paths = paths.Replace("~/", GetBasePath());
                string relativePath = Path.Combine(GetTempPath(), string.Format("Download_{0}.zip", DateTime.Now.ToString("yyyyMMdd_hhmmss")));
                string absolutePath = VirtualPathUtility.ToAbsolute(relativePath);
                string dest = Server.MapPath(relativePath);
                JsonResponse response = ZipHelper.GenerateZipFile(paths, dest, "", true);
                if (response.success)
                {
                    JsonResponse downloadRes = new JsonResponse();
                    downloadRes.success = true;
                    downloadRes.message = absolutePath;
                    return downloadRes;
                }
                else
                {
                    return response;
                }
            }
        }

        #region 属性修改
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public JsonResponse SetFileAttributes(string path, bool isReadOnly, bool isHidden, bool isSystem, bool isArchive, bool isWritable, bool isBrowsable)
        {
            path = path.Replace("~/", config.BasePath);
            if (Allowed(path, "w"))
            {
                path = Server.MapPath(path);
                return FileHelper.SetFileAttributes(path, isReadOnly, isHidden, isSystem, isArchive, isWritable, isBrowsable);
            }
            else
            {
                JsonResponse response = new JsonResponse();
                response.success = false;
                response.message = string.Format("文件\"{0}\"被保护，您不能对\"{0}\"进行编辑", path);
                return response;
            }
        }

        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public JsonResponse SetFolderAttributes(string path, bool isReadOnly, bool isHidden, bool isSystem, bool isArchive,  bool isWritable, bool isBrowsable, bool recursive)
        {
            path = path.Replace("~/", config.BasePath);
            if (Allowed(path, "w"))
            {
                path = Server.MapPath(path);
                return FileHelper.SetFolderAttributes(path, isReadOnly, isHidden, isSystem, isArchive, isWritable, isBrowsable, recursive);
            }
            else
            {
                JsonResponse response = new JsonResponse();
                response.success = false;
                response.message = string.Format("文件夹\"{0}\"被保护，您不能对\"{0}\"进行编辑", path);
                return response;
            }
        }
        #endregion

        #region Create New
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public JsonResponse NewFile(string path, string name)
        {
            path = path.Replace("~/", config.BasePath);
            if (Allowed(path, "w"))
            {
                string destPath = Server.MapPath(path);
                return FileHelper.CreateTextFile(destPath, name, false, "");
            }
            else
            {
                JsonResponse response = new JsonResponse();
                response.success = false;
                response.message = string.Format("文件夹\"{0}\"被保护，您不能在\"{0}\"添加文件", path);
                return response;
            }
        }

        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public JsonResponse NewFolder(string path, string name)
        {
            path = path.Replace("~/", config.BasePath);
            if (Allowed(path, "w"))
            {
                string destPath = Server.MapPath(path);
                return FileHelper.CreateFolder(destPath, name);
            }
            else
            {
                JsonResponse response = new JsonResponse();
                response.success = false;
                response.message = string.Format("文件夹\"{0}\"被保护，您不能在\"{0}\"添加文件夹", path);
                return response;
            }
        }
        #endregion
    }
}
